﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;

#endregion

#region COPYRIGHT

/*
    Copyright (c) 2008, 2009, 2010 
        Roland Rosenkranz (Glatzemann@email.de)
*/

#endregion

#region LICENSE

/*
    This file is part of starLiGHT.Collision.

    starLiGHT.Collision is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    starLiGHT.Collision is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with starLiGHT.Collision.  If not, see <http://www.gnu.org/licenses/>.

    
    ADDITIONAL (commercial) LICENSES for starLiGHT.Collision are available on request.
*/

#endregion

#region Blaze Copyright
/* 
*  Copyright (c) 2008 Rene Schulte. http://www.rene-schulte.info/ 
*  Ported to D by Mason Green. http:/www.dsource.org/projects/blaze 
* 
*   This software is provided 'as-is', without any express or implied 
*   warranty. In no event will the authors be held liable for any damages 
*   arising from the use of this software. 
* 
*   Permission is granted to anyone to use this software for any purpose, 
*   including commercial applications, and to alter it and redistribute it 
*   freely, subject to the following restrictions: 
* 
*   1. The origin of this software must not be misrepresented; you must not 
*   claim that you wrote the original software. If you use this software 
*   in a product, an acknowledgment in the product documentation would be 
*   appreciated but is not required. 
* 
*   2. Altered source versions must be plainly marked as such, and must not be 
*   misrepresented as being the original software. 
* 
*   3. This notice may not be removed or altered from any source 
*   distribution. 
*/ 
#endregion

#region Version Stuff
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 1486                  $:  Revision of last commit *
// * $Author:: glatzemann         $:  Author of last commit   *
// * $Date:: 2010-10-08 15:55:47 #$:  Date of last commit     *
// ************************************************************

// **************[ Blaze-Repository Info ]*********************
// File       : http://www.dsource.org/projects/blaze/browser/trunk/blaze/collision/shapes/bzFluidParticle.d
// Revision   : 484
// Change-Date: 2009-03-14
//
// Status     : Porting
#endregion

namespace starLiGHT.Physic.TwoD
{
    public class FluidParticle : Fixture
    {
        internal Vector2 velocity;
        internal Vector2 position;
        internal Vector2 positionOld;
        internal float mass;
        internal float massInv;
        internal float density;
        internal Vector2 force;
        internal float pressure;
        internal Dictionary<int, FluidParticle> neighbors;
        internal float gridSize;
        internal float margin;
        internal int ID;

        public FluidParticle(Vector2 position, float restitution, float friction, World world)
        {
            base.m_shape = new FluidShape(this);
            BodyDef bd = new BodyDef();
            bd.position = position;
            bd.type = BodyType.KINEMATIC;
            base.m_body = new Body(bd, world);

            //base.m_type = ShapeType.FLUID;
            base.m_restitution = restitution;
            base.m_friction = friction;
            setMass(1.25f);
            gridSize = PhysicSettings.CELL_SPACE * 2f;
            margin = 0.01f;
            this.position = position;
            this.density = PhysicSettings.DENSITY_OFFSET;

            // create proxy
            Transform dummy = new Transform();
            base.CreateProxies(world.m_contactManager.m_broadPhase, dummy);
            updatePressure();
        }

        public void updatePressure()
        {
            pressure = PhysicSettings.GAS_CONSTANT * (density - PhysicSettings.DENSITY_OFFSET);
        }

        public void update(TimeStep step, Vector2 gravity)
        {
            Vector2 acceleration = force * massInv;
            acceleration += gravity;

            // Verlet integration
            Vector2 t;
            float damping = 0.01f;
            Vector2 oldPos = position;
            // Position = Position + (1.0f - Damping) * (Position - PositionOld) + dt * dt * a;
            acceleration *= (step.dt * step.dt);
            t = position - positionOld;
            t *= (1.0f - damping);
            t += acceleration;
            position += t;
            positionOld = oldPos;

            // calculate velocity
            // Velocity = (Position - PositionOld) / dt;
            t = position - positionOld;
            velocity = t * 1.0f * step.inv_dt;
        }

        public Vector2 worldCenter()
        {
            return position;
        }

        public void setMass(float mass)
        {
            this.mass = mass;
            massInv = mass > 0.0f ? 1.0f / mass : 0.0f;
        }

        public void addNeighbor(FluidParticle p)
        {
            if (p != null)
            {
                neighbors[p.ID] = p;
            }
            else
            {
                System.Diagnostics.Debugger.Break();
            }
        }

        public void removeNeighbor(FluidParticle p)
        {
            neighbors.Remove(p.ID);
        }

        public void addForce(Vector2 force)
        {
            this.force += force;
        }

    }
}
